﻿using System.Collections;

namespace DimensionsHelper.LanguageService.Syntax;

public class MetadataDbProperties : Declaration, IReadOnlyList<MetadataProperty>
{
    private MetadataDbColumns? _columns;


    private SyntaxList<MetadataProperty>? _properties;

    internal MetadataDbProperties(SyntaxToken dbKeywordToken, SyntaxNode? parent) :
        base(SyntaxKinds.MetadataDbProperties,
            dbKeywordToken,
            NodeConverter.ToIdentifier(dbKeywordToken),
            parent)
    {
    }

    public MetadataDbColumns? Columns => _columns;

    public int Count => _properties?.Count ?? 0;


    public MetadataProperty this[int index] =>
        _properties == null
            ? throw new IndexOutOfRangeException(nameof(index))
            : _properties[index];


    public IEnumerator<MetadataProperty> GetEnumerator()
    {
        return _properties?.GetEnumerator() ??
               Enumerable.Empty<MetadataProperty>().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }


    public void Update(MetadataDbColumns columns)
    {
        SetChildNullableField(ref _columns, columns);
    }


    public void Add(MetadataProperty property)
    {
        AddChildMember(ref _properties, property);
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, DeclareKeywordToken, Columns);
        AcceptList(visitor, _properties);
    }
}


public static partial class NodeFactory
{
    public static MetadataDbProperties CreateMetadataDbProperties(SyntaxNode? parent,
        SyntaxToken dbKeyword, MetadataDbColumns? columns, IEnumerable<MetadataProperty?>? properties)
    {
        MetadataDbProperties dbProperties = new(dbKeyword, parent);

        if (columns != null)
        {
            dbProperties.Update(columns);
        }

        if (properties != null)
        {
            foreach (MetadataProperty? prop in properties)
            {
                if (prop != null)
                {
                    dbProperties.Add(prop);
                }
            }
        }

        return dbProperties;
    }
}